<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\CustHub\Constants\OpSchemeTypeConstants;
use App\CustHub\Dto\OperationLogDto;
use App\CustHub\Event\ChOperationLog;
use App\CustHub\Event\RoomActiveRoom;
use App\CustHub\Mapper\ChOpSchemeMapper;
use App\CustHub\Mapper\ChOpSchemeRobotMapper;
use App\CustHub\Model\ChOpSchemeRobot;
use App\CustHub\Model\ChOpSchemeRobotLog;
use App\CustHub\Model\ChRobot;
use Carbon\Carbon;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractService;
use Mine\Annotation\Transaction;
use Mine\MineModel;
use function Hyperf\Collection\collect;
use function Hyperf\Collection\value;

class ChOpSchemeRobotService extends AbstractService
{
    public $mapper;

    #[Inject]
    protected ChOpSchemeMapper $opSchemeMapper;

    #[Inject]
    protected ChSendConfigService $sendConfigService;


    public function __construct(ChOpSchemeRobotMapper $mapper)
    {
        $this->mapper = $mapper;
    }


    public function list(array $params): array
    {
        $schemeId = $params['scheme_id'];

        $schemeInfo = $this->opSchemeMapper->findById($schemeId);
        $type = OpSchemeTypeConstants::getSendConfigType($schemeInfo->type);
        $pageSize = $params['page_size'] ?? MineModel::PAGE_SIZE;
        $paginate = $this->mapper->model::query()
            ->select(['id', 'main_uid', 'scheme_id', 'robot_id', 'status', 'type', 'updated_at'])
            ->with(['robot' => function ($query) {
                $query->select(['id', 'nickname', 'avatar', 'corp_name']);
            }, 'config' => function ($query) use ($type) {
                $query->select(['id', 'robot_id', 'type', 'value'])->where('type', $type);
            }])
            ->where('scheme_id', $schemeId)
            ->orderBy('id', 'desc')
            ->paginate((int)$pageSize);

        $paginate->getCollection()->transform(function ($item) {
            if (empty($item->config)) {
                $type = OpSchemeTypeConstants::getSendConfigType($item->type);
                $sendConfig = $this->sendConfigService->getConfig($type, $item->main_uid, $item->robot_id, true);
                $item->config_value = $sendConfig;
            }else{
                $item->config_value = $item->config->value;
            }
            unset($item->config);
            return $item;
        });

        $response = $this->mapper->setPaginate($paginate);
        $response['scheme_name'] = $schemeInfo['name'] ?? '';
        $response['scheme_updated_at'] = !empty($schemeInfo['updated_at']) ? $schemeInfo['updated_at']->toDateTimeString() : '';
        return $response;
    }

    /**
     * 批量修改状态
     * @param array $params
     * @return bool|int
     */
    public function batchChangeStatus(array $params): bool|int
    {
        $ids = json_decode($params['ids'], true);


        $models = $this->mapper->model::query()
            ->with(['scheme'=>function ($query) {
                $query->select(['id','name','type']);
            }])
            ->whereIn('id',$ids)
            ->get();
        foreach ($models as $model){
            event((new ChOperationLog(
                (new OperationLogDto())
                    ->setUid($params['uid'])
                    ->setMainUid($params['main_uid'])
                    ->setSchemeId($model->scheme_id)
                    ->setName($model->scheme->name ?? '')
                    ->setContent($params['status'] == 1 ? '方案开启' : '方案关闭')
                    ->setType($model->type)
                    ->setRobotIds([$model->robot_id])
            )));
            $model->status = $params['status'];
            $model->save();
        }
        return true;
//        return $this->mapper->model::query()
//            ->whereIn('id', $ids)
//            ->update(['status' => $params['status']]);
    }

    /**
     * 批量取消
     * @param array $params
     * @return bool|int|mixed|null
     * @throws \Exception
     */
    public function batchCancel(array $params): mixed
    {
        $ids = json_decode($params['ids'], true);

        $models = $this->mapper->model::query()
            ->with(['scheme'=>function ($query) {
                $query->select(['id','name','type']);
            }])
            ->whereIn('id',$ids)
            ->get();

        foreach ($models as $model){
            event((new ChOperationLog(
                (new OperationLogDto())
                    ->setUid($params['uid'])
                    ->setMainUid($params['main_uid'])
                    ->setSchemeId($model->scheme_id)
                    ->setName($model->scheme->name ?? '')
                    ->setContent('企微号取消应用方案')
                    ->setType($model->type)
                    ->setRobotIds([$model->robot_id])
            )));
            $model->delete();
        }
        return true;
//        return $this->mapper->model::query()
//            ->whereIn('id', $ids)
//            ->delete();
    }

    /**
     * 方案应用记录
     * @param array $params
     * @return array
     */
    public function record(array $params): array
    {
        $pageSize = $params['page_size'] ?? MineModel::PAGE_SIZE;
        $corpId = $params['corp_id'] ?? '';
        $type = $params['type'];
        $paginate = ChOpSchemeRobotLog::query()
            ->with(['schemes' => function ($query) {
                $query->select(['id', 'name']);
            }, 'robots' => function ($query) {
                $query->select(['id', 'nickname', 'avatar']);
            }])->whereHas('schemes', function ($query) use ($corpId, $type) {
                $query->when(!empty($corpId), function ($query) use ($corpId) {
                    $query->where('corp_id', $corpId);
                })->where('type', $type);
            })->where('uid', $params['uid'])
            ->orderBy('id', 'desc')
            ->paginate((int)$pageSize);
        return $this->mapper->setPaginate($paginate);
    }

    #[Transaction]
    public function applicationScheme(array $params): bool
    {
        $schemeIds = json_decode($params['scheme_ids'], true);

        $uid = $params['uid'];
        $mainUid = $params['main_uid'];

        if (empty($params['robot_ids'])) {
            //选择所有机器人的情况
            $robotList = container()->get(ChRobotService::class)->getRobotListByUid($uid);
            $robotIds = collect($robotList)->pluck('id')->toArray();
        } else {
            $robotIds = json_decode($params['robot_ids'], true);
        }

        $schemeList = $this->opSchemeMapper->model::query()
            ->select(['id','name','type','is_default'])
            ->whereIn('id', $schemeIds)
            ->get();

        $schemeMap = collect($schemeList)->pluck('name','id')->toArray();

        $data = [];
        $type = null;
        $defaultSchemeIds = [];
        foreach ($schemeList as $item) {
            $type = $item['type'];
            $schemeId = $item['id'];
            if($item['is_default'] == 1){
                $defaultSchemeIds[] = $schemeId;
            }
            foreach ($robotIds as $robotId) {
                $data[] = [
                    'scheme_id' => $schemeId,
                    'robot_id' => $robotId,
                    'uid' => $uid,
                    'main_uid' => $mainUid,
                    'type' => $type,
                    'created_at' => Carbon::now()->toDateTimeString(),
                    'updated_at' => Carbon::now()->toDateTimeString()
                ];
            }
        }
        //查询出已经设置过机器人的方案
        $existingSchemes = $this->mapper->model::select(['id', 'scheme_id', 'robot_id'])
            ->whereIn('scheme_id', $schemeIds)
            ->whereIn('robot_id', $robotIds)
            ->get();

        $existingSchemes = $existingSchemes->mapWithKeys(function ($item) {
            return [$item['scheme_id'] . '_' . $item['robot_id'] => $item['id']];
        });

        //需要更新的数据
        $toUpdate = collect($data)->filter(function ($item) use ($existingSchemes) {
            $key = $item['scheme_id'] . '_' . $item['robot_id'];
            return $existingSchemes->has($key);
        })->map(function ($item) use ($existingSchemes) {
            $item['id'] = $existingSchemes->get($item['scheme_id'] . '_' . $item['robot_id']);
            unset($item['created_at']);
            return $item;
        });

        //需要新增的数据
        $toInsert = collect($data)->reject(function ($item) use ($existingSchemes) {
            $key = $item['scheme_id'] . '_' . $item['robot_id'];
            return $existingSchemes->has($key);
        });

        if ($toUpdate->isNotEmpty()) {
            ChOpSchemeRobot::upsert($toUpdate->toArray(), ['id']);
        }

        if ($toInsert->isNotEmpty()) {

            $toInsert = $toInsert->toArray();
            $newCustomerRobotIds = [];
            foreach ($toInsert as $item){
                if($item['type'] == OpSchemeTypeConstants::NEW_CUSTOMER && in_array($item['scheme_id'],$defaultSchemeIds)){
                    $newCustomerRobotIds[] = $item['robot_id'];
                }
            }

            if(!empty($newCustomerRobotIds)){
                $needDeleteIds = $this->mapper->model::query()
                    ->whereIn('robot_id',$newCustomerRobotIds)
                    ->where('type',OpSchemeTypeConstants::NEW_CUSTOMER)
                    ->whereHas('scheme',function ($query){
                        $query->where('is_default',1);
                    })
                    ->pluck('id')
                    ->toArray();

                if(!empty($needDeleteIds)){
                    $this->mapper->model::query()
                        ->whereIn('id',$needDeleteIds)
                        ->delete();
                }
            }

            ChOpSchemeRobot::insert($toInsert);
            $toInsertMap = collect($toInsert)->groupBy('scheme_id')->toArray();
            foreach ($toInsertMap as $schemeId => $item){
                $robotIds = array_column($item,'robot_id');
                event((new ChOperationLog(
                    (new OperationLogDto())
                        ->setUid($uid)
                        ->setMainUid($mainUid)
                        ->setSchemeId($schemeId)
                        ->setName($schemeMap[$schemeId] ?? '')
                        ->setContent('应用企微号')
                        ->setType($type)
                        ->setRobotIds($robotIds)
                )));
            }

        }
        //存储应用记录
        $schemeRobotLogData = [
            'uid' => $uid,
            'main_uid' => $mainUid,
            'created_at' => Carbon::now()->toDateTimeString(),
            'updated_at' => Carbon::now()->toDateTimeString()
        ];
        $schemeRobotLog = ChOpSchemeRobotLog::create($schemeRobotLogData);
        $schemeRobotLog->schemes()->attach($schemeIds);
        $schemeRobotLog->robots()->attach($robotIds);
        //处理生效群
        event(new RoomActiveRoom($schemeIds,$robotIds,$type));
        return true;
    }
}